﻿/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine - OpenGL Plugin
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#include "OpenGLPlugin.h"
#include <Windows.h>

#define WGL_WGLEXT_PROTOTYPES 1

#include <assert.h> 

#include <GL/GL.h>
#include "glext.h"
#include "wglext.h"
#include "opengl_api.h"

#include <GL/GLU.h>
#include <GL/glut.h>

#include <vector>
#include <string>

#include <algorithm>

#include <sstream>
using namespace std;

using namespace Omen;

//=============================================================================
/**
**
**
*/
DWORD WindowWidth = 1024;
DWORD WindowHeight = 768;

HWND  OpenGLWindowHandle = NULL;
HDC   OpenGLWindowDeviceContext = NULL;

GLint g_gl_iMajorVersion, g_gl_iMinorVersion;

//=============================================================================
/**
**
**
*/
OpenGLGraphicsDriver::OpenGLGraphicsDriver() :
    m_bIsActive(false)
{
}

//=============================================================================
/**
** <summary>Destroys an OpenGL graphics driver</summary>
**
*/
/*OpenGLGraphicsDriver::~OpenGLGraphicsDriver() 
{ 
}*/

//=============================================================================
/**
** <summary>Destroys an OpenGL graphics driver</summary>
**
*/
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)        // Resize And Initialize The GL Window
{
    WindowWidth = width;
    WindowHeight = height;

    if (height==0)                                        // Prevent A Divide By Zero By
    {
        height=1;                                        // Making Height Equal One
    }

    glViewport(0,0,width,height);                        // Reset The Current Viewport

    glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
    glLoadIdentity();                                    // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);                            // Select The Modelview Matrix
    glLoadIdentity();                                    // Reset The Modelview Matrix
}

static bool checkGLVersion( const GLint& iMajor, const GLint& iMinor )
{
    return g_gl_iMajorVersion > iMajor ||
           g_gl_iMajorVersion == iMajor && g_gl_iMinorVersion >= iMinor;
}

//=============================================================================
/**
** <summary>Init OpenGL API calls</summary>
**
*/
static void InitOpenGLAPI()
{
    glGetIntegerv(GL_MAJOR_VERSION, &g_gl_iMajorVersion);
    glGetIntegerv(GL_MINOR_VERSION, &g_gl_iMinorVersion);
    
    // OpenGL 1.2 and above
    if( checkGLVersion(1,2) )
    {
        glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)wglGetProcAddress("glCopyTexSubImage3D"); assert(glCopyTexSubImage3D);
        glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)wglGetProcAddress("glDrawRangeElements");assert(glDrawRangeElements);
        glTexImage3D        = (PFNGLTEXIMAGE3DPROC)wglGetProcAddress("glTexImage3D");assert(glTexImage3D);
        glTexSubImage3D     = (PFNGLTEXSUBIMAGE3DPROC)wglGetProcAddress("glTexSubImage3D");assert(glTexSubImage3D);
    }

    // OpenGL 1.3 and above
    if( checkGLVersion(1,3) )
    {
        // Texture activation
        glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture"); assert(glActiveTexture);
        glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture"); assert(glClientActiveTexture);

        // Compressed Texture
        glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)wglGetProcAddress("glCompressedTexImage1D"); assert(glCompressedTexImage1D);
        glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2D"); assert(glCompressedTexImage2D);
        glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)wglGetProcAddress("glCompressedTexImage3D"); assert(glCompressedTexImage3D);
        
        // Compressed Sub Texture
        glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)wglGetProcAddress("glCompressedTexSubImage1D"); assert(glCompressedTexSubImage1D);
        glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)wglGetProcAddress("glCompressedTexSubImage2D"); assert(glCompressedTexSubImage2D);
        glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)wglGetProcAddress("glCompressedTexSubImage3D"); assert(glCompressedTexSubImage3D);
        
        // Get Compressed Texture Image
        glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)wglGetProcAddress("glGetCompressedTexImage"); assert(glGetCompressedTexImage);
        
        // Transpose Matrix functions
        glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)wglGetProcAddress("glLoadTransposeMatrixd"); assert(glLoadTransposeMatrixd);
        glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)wglGetProcAddress("glLoadTransposeMatrixf"); assert(glLoadTransposeMatrixf);
        glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)wglGetProcAddress("glMultTransposeMatrixd"); assert(glMultTransposeMatrixd);
        glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)wglGetProcAddress("glMultTransposeMatrixf"); assert(glMultTransposeMatrixf);
        
        glMultiTexCoord1d   = (PFNGLMULTITEXCOORD1DPROC)wglGetProcAddress("glMultiTexCoord1d"); assert(glMultiTexCoord1d);
        glMultiTexCoord1dv  = (PFNGLMULTITEXCOORD1DVPROC)wglGetProcAddress("glMultiTexCoord1dv"); assert(glMultiTexCoord1dv);
        glMultiTexCoord1f   = (PFNGLMULTITEXCOORD1FPROC)wglGetProcAddress("glMultiTexCoord1f"); assert(glMultiTexCoord1f);
        glMultiTexCoord1fv  = (PFNGLMULTITEXCOORD1FVPROC)wglGetProcAddress("glMultiTexCoord1fv"); assert(glMultiTexCoord1fv);
        glMultiTexCoord1i   = (PFNGLMULTITEXCOORD1IPROC)wglGetProcAddress("glMultiTexCoord1i"); assert(glMultiTexCoord1i);
        glMultiTexCoord1iv  = (PFNGLMULTITEXCOORD1IVPROC)wglGetProcAddress("glMultiTexCoord1iv"); assert(glMultiTexCoord1iv);
        glMultiTexCoord1s   = (PFNGLMULTITEXCOORD1SPROC)wglGetProcAddress("glMultiTexCoord1s"); assert(glMultiTexCoord1s);
        glMultiTexCoord1sv  = (PFNGLMULTITEXCOORD1SVPROC)wglGetProcAddress("glMultiTexCoord1sv"); assert(glMultiTexCoord1sv);
        glMultiTexCoord2d   = (PFNGLMULTITEXCOORD2DPROC)wglGetProcAddress("glMultiTexCoord2d"); assert(glMultiTexCoord2d);
        glMultiTexCoord2dv  = (PFNGLMULTITEXCOORD2DVPROC)wglGetProcAddress("glMultiTexCoord2dv"); assert(glMultiTexCoord2dv);
        glMultiTexCoord2f   = (PFNGLMULTITEXCOORD2FPROC)wglGetProcAddress("glMultiTexCoord2f"); assert(glMultiTexCoord2f);
        glMultiTexCoord2fv  = (PFNGLMULTITEXCOORD2FVPROC)wglGetProcAddress("glMultiTexCoord2fv"); assert(glMultiTexCoord2fv);
        glMultiTexCoord2i   = (PFNGLMULTITEXCOORD2IPROC)wglGetProcAddress("glMultiTexCoord2i"); assert(glMultiTexCoord2i);
        glMultiTexCoord2iv  = (PFNGLMULTITEXCOORD2IVPROC)wglGetProcAddress("glMultiTexCoord2iv"); assert(glMultiTexCoord2iv);
        glMultiTexCoord2s   = (PFNGLMULTITEXCOORD2SPROC)wglGetProcAddress("glMultiTexCoord2s"); assert(glMultiTexCoord2s);
        glMultiTexCoord2sv  = (PFNGLMULTITEXCOORD2SVPROC)wglGetProcAddress("glMultiTexCoord2sv"); assert(glMultiTexCoord2sv);
        glMultiTexCoord3d   = (PFNGLMULTITEXCOORD3DPROC)wglGetProcAddress("glMultiTexCoord3d"); assert(glMultiTexCoord3d);
        glMultiTexCoord3dv  = (PFNGLMULTITEXCOORD3DVPROC)wglGetProcAddress("glMultiTexCoord3dv"); assert(glMultiTexCoord3dv);
        glMultiTexCoord3f   = (PFNGLMULTITEXCOORD3FPROC)wglGetProcAddress("glMultiTexCoord3f"); assert(glMultiTexCoord3f);
        glMultiTexCoord3fv  = (PFNGLMULTITEXCOORD3FVPROC)wglGetProcAddress("glMultiTexCoord3fv"); assert(glMultiTexCoord3fv);
        glMultiTexCoord3i   = (PFNGLMULTITEXCOORD3IPROC)wglGetProcAddress("glMultiTexCoord3i"); assert(glMultiTexCoord3i);
        glMultiTexCoord3iv  = (PFNGLMULTITEXCOORD3IVPROC)wglGetProcAddress("glMultiTexCoord3iv"); assert(glMultiTexCoord3iv);
        glMultiTexCoord3s   = (PFNGLMULTITEXCOORD3SPROC)wglGetProcAddress("glMultiTexCoord3s"); assert(glMultiTexCoord3s);
        glMultiTexCoord3sv  = (PFNGLMULTITEXCOORD3SVPROC)wglGetProcAddress("glMultiTexCoord3sv"); assert(glMultiTexCoord3sv);
        glMultiTexCoord4d   = (PFNGLMULTITEXCOORD4DPROC)wglGetProcAddress("glMultiTexCoord4d"); assert(glMultiTexCoord4d);
        glMultiTexCoord4dv  = (PFNGLMULTITEXCOORD4DVPROC)wglGetProcAddress("glMultiTexCoord4dv"); assert(glMultiTexCoord4dv);
        glMultiTexCoord4f   = (PFNGLMULTITEXCOORD4FPROC)wglGetProcAddress("glMultiTexCoord4f"); assert(glMultiTexCoord4f);
        glMultiTexCoord4fv  = (PFNGLMULTITEXCOORD4FVPROC)wglGetProcAddress("glMultiTexCoord4fv"); assert(glMultiTexCoord4fv);
        glMultiTexCoord4i   = (PFNGLMULTITEXCOORD4IPROC)wglGetProcAddress("glMultiTexCoord4i"); assert(glMultiTexCoord4i);
        glMultiTexCoord4iv  = (PFNGLMULTITEXCOORD4IVPROC)wglGetProcAddress("glMultiTexCoord4iv"); assert(glMultiTexCoord4iv);
        glMultiTexCoord4s   = (PFNGLMULTITEXCOORD4SPROC)wglGetProcAddress("glMultiTexCoord4s"); assert(glMultiTexCoord4s);
        glMultiTexCoord4sv  = (PFNGLMULTITEXCOORD4SVPROC)wglGetProcAddress("glMultiTexCoord4sv"); assert(glMultiTexCoord4sv);
        glSampleCoverage    = (PFNGLSAMPLECOVERAGEPROC)wglGetProcAddress("glSampleCoverage"); assert(glSampleCoverage);
    }

    // OpenGL 1.4 and above
    if( checkGLVersion( 1, 4 ) )
    {
        glBlendColor = (PFNGLBLENDCOLORPROC)wglGetProcAddress("glBlendColor"); assert(glBlendColor);
        glBlendEquation  = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation"); assert(glBlendEquation);
        glBlendFuncSeparate  = (PFNGLBLENDFUNCSEPARATEPROC)wglGetProcAddress("glBlendFuncSeparate"); assert(glBlendFuncSeparate);
        glFogCoordPointer  = (PFNGLFOGCOORDPOINTERPROC)wglGetProcAddress("glFogCoordPointer"); assert(glFogCoordPointer);
        glFogCoordd  = (PFNGLFOGCOORDDPROC)wglGetProcAddress("glFogCoordd"); assert(glFogCoordd);
        glFogCoorddv  = (PFNGLFOGCOORDDVPROC)wglGetProcAddress("glFogCoorddv"); assert(glFogCoorddv);
        glFogCoordf  = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordf"); assert(glFogCoordf);
        glFogCoordfv  = (PFNGLFOGCOORDFVPROC)wglGetProcAddress("glFogCoordfv"); assert(glFogCoordfv);
        glMultiDrawArrays  = (PFNGLMULTIDRAWARRAYSPROC)wglGetProcAddress("glMultiDrawArrays"); assert(glMultiDrawArrays);
        glMultiDrawElements  = (PFNGLMULTIDRAWELEMENTSPROC)wglGetProcAddress("glMultiDrawElements"); assert(glMultiDrawElements);
        glPointParameterf  = (PFNGLPOINTPARAMETERFPROC)wglGetProcAddress("glPointParameterf"); assert(glPointParameterf);
        glPointParameterfv  = (PFNGLPOINTPARAMETERFVPROC)wglGetProcAddress("glPointParameterfv"); assert(glPointParameterfv);
        glPointParameteri  = (PFNGLPOINTPARAMETERIPROC)wglGetProcAddress("glPointParameteri"); assert(glPointParameteri);
        glPointParameteriv  = (PFNGLPOINTPARAMETERIVPROC)wglGetProcAddress("glPointParameteriv"); assert(glPointParameteriv);
        glSecondaryColor3b  = (PFNGLSECONDARYCOLOR3BPROC)wglGetProcAddress("glSecondaryColor3b"); assert(glSecondaryColor3b);
        glSecondaryColor3bv  = (PFNGLSECONDARYCOLOR3BPROC)wglGetProcAddress("glSecondaryColor3bv"); assert(glSecondaryColor3bv);
        glSecondaryColor3d  = (PFNGLSECONDARYCOLOR3DPROC)wglGetProcAddress("glSecondaryColor3d"); assert(glSecondaryColor3d);
        glSecondaryColor3dv  = (PFNGLSECONDARYCOLOR3DVPROC)wglGetProcAddress("glSecondaryColor3dv"); assert(glSecondaryColor3dv);
        glSecondaryColor3f  = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f"); assert(glSecondaryColor3f);
        glSecondaryColor3fv  = (PFNGLSECONDARYCOLOR3FVPROC)wglGetProcAddress("glSecondaryColor3fv"); assert(glSecondaryColor3fv);
        glSecondaryColor3i  = (PFNGLSECONDARYCOLOR3IPROC)wglGetProcAddress("glSecondaryColor3i"); assert(glSecondaryColor3i);
        glSecondaryColor3iv  = (PFNGLSECONDARYCOLOR3IVPROC)wglGetProcAddress("glSecondaryColor3iv"); assert(glSecondaryColor3iv);
        glSecondaryColor3s  = (PFNGLSECONDARYCOLOR3SPROC)wglGetProcAddress("glSecondaryColor3s"); assert(glSecondaryColor3s);
        glSecondaryColor3sv  = (PFNGLSECONDARYCOLOR3SVPROC)wglGetProcAddress("glSecondaryColor3sv"); assert(glSecondaryColor3sv);
        glSecondaryColor3ub  = (PFNGLSECONDARYCOLOR3UBPROC)wglGetProcAddress("glSecondaryColor3ub"); assert(glSecondaryColor3ub);
        glSecondaryColor3ubv  = (PFNGLSECONDARYCOLOR3UBVPROC)wglGetProcAddress("glSecondaryColor3ubv"); assert(glSecondaryColor3ubv);
        glSecondaryColor3ui  = (PFNGLSECONDARYCOLOR3UIPROC)wglGetProcAddress("glSecondaryColor3ui"); assert(glSecondaryColor3ui);
        glSecondaryColor3uiv  = (PFNGLSECONDARYCOLOR3UIVPROC)wglGetProcAddress("glSecondaryColor3uiv"); assert(glSecondaryColor3uiv);
        glSecondaryColor3us  = (PFNGLSECONDARYCOLOR3USPROC)wglGetProcAddress("glSecondaryColor3us"); assert(glSecondaryColor3us);
        glSecondaryColor3usv  = (PFNGLSECONDARYCOLOR3USVPROC)wglGetProcAddress("glSecondaryColor3usv"); assert(glSecondaryColor3usv);
        glSecondaryColorPointer  = (PFNGLSECONDARYCOLORPOINTERPROC)wglGetProcAddress("glSecondaryColorPointer"); assert(glSecondaryColorPointer);
        glWindowPos2d  = (PFNGLWINDOWPOS2DPROC)wglGetProcAddress("glWindowPos2d"); assert(glWindowPos2d);
        glWindowPos2dv  = (PFNGLWINDOWPOS2DVPROC)wglGetProcAddress("glWindowPos2dv"); assert(glWindowPos2dv);
        glWindowPos2f  = (PFNGLWINDOWPOS2FPROC)wglGetProcAddress("glWindowPos2f"); assert(glWindowPos2f);
        glWindowPos2fv  = (PFNGLWINDOWPOS2FVPROC)wglGetProcAddress("glWindowPos2fv"); assert(glWindowPos2fv);
        glWindowPos2i  = (PFNGLWINDOWPOS2IPROC)wglGetProcAddress("glWindowPos2i"); assert(glWindowPos2i);
        glWindowPos2iv  = (PFNGLWINDOWPOS2IVPROC)wglGetProcAddress("glWindowPos2iv"); assert(glWindowPos2iv);
        glWindowPos2s  = (PFNGLWINDOWPOS2SPROC)wglGetProcAddress("glWindowPos2s"); assert(glWindowPos2s);
        glWindowPos2sv  = (PFNGLWINDOWPOS2SVPROC)wglGetProcAddress("glWindowPos2sv"); assert(glWindowPos2sv);
        glWindowPos3d  = (PFNGLWINDOWPOS3DPROC)wglGetProcAddress("glWindowPos3d"); assert(glWindowPos3d);
        glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)wglGetProcAddress("glWindowPos3dv"); assert(glWindowPos3dv);
        glWindowPos3f  = (PFNGLWINDOWPOS3FPROC)wglGetProcAddress("glWindowPos3f"); assert(glWindowPos3f);
        glWindowPos3fv  = (PFNGLWINDOWPOS3FVPROC)wglGetProcAddress("glWindowPos3fv"); assert(glWindowPos3fv);
        glWindowPos3i  = (PFNGLWINDOWPOS3IPROC)wglGetProcAddress("glWindowPos3i"); assert(glWindowPos3i);
        glWindowPos3iv  = (PFNGLWINDOWPOS3IVPROC)wglGetProcAddress("glWindowPos3iv"); assert(glWindowPos3iv);
        glWindowPos3s  = (PFNGLWINDOWPOS3SPROC)wglGetProcAddress("glWindowPos3s"); assert(glWindowPos3s);
        glWindowPos3sv  = (PFNGLWINDOWPOS3SVPROC)wglGetProcAddress("glWindowPos3sv"); assert(glWindowPos3sv);
    }

    // OpenGL 1.5 and above
    if( checkGLVersion( 1, 5 ) )
    {
        glGenQueries = (PFNGLGENQUERIESPROC)wglGetProcAddress("glGenQueries"); assert(glGenQueries);
        glDeleteQueries  = (PFNGLDELETEQUERIESPROC)wglGetProcAddress("glDeleteQueries"); assert(glDeleteQueries);
        glIsQuery  = (PFNGLISQUERYPROC)wglGetProcAddress("glIsQuery"); assert(glIsQuery);
        glBeginQuery  = (PFNGLBEGINQUERYPROC)wglGetProcAddress("glBeginQuery"); assert(glBeginQuery);
        glEndQuery  = (PFNGLENDQUERYPROC)wglGetProcAddress("glEndQuery"); assert(glEndQuery);
        glGetQueryiv  = (PFNGLGETQUERYIVPROC)wglGetProcAddress("glGetQueryiv"); assert(glGetQueryiv);
        glGetQueryObjectiv  = (PFNGLGETQUERYOBJECTIVPROC)wglGetProcAddress("glGetQueryObjectiv"); assert(glGetQueryObjectiv);
        glGetQueryObjectuiv  = (PFNGLGETQUERYOBJECTUIVPROC)wglGetProcAddress("glGetQueryObjectuiv"); assert(glGetQueryObjectuiv);
        glBindBuffer  = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer"); assert(glBindBuffer);
        glDeleteBuffers  = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers"); assert(glDeleteBuffers);
        glGenBuffers  = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers"); assert(glGenBuffers);
        glIsBuffer  = (PFNGLISBUFFERPROC)wglGetProcAddress("glIsBuffer"); assert(glIsBuffer);
        glBufferData  = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData"); assert(glBufferData);
        glBufferSubData  = (PFNGLBUFFERSUBDATAPROC)wglGetProcAddress("glBufferSubData"); assert(glBufferSubData);
        glGetBufferSubData  = (PFNGLGETBUFFERSUBDATAPROC)wglGetProcAddress("glGetBufferSubData"); assert(glGetBufferSubData);
        glMapBuffer  = (PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer"); assert(glMapBuffer);
        glUnmapBuffer  = (PFNGLUNMAPBUFFERPROC)wglGetProcAddress("glUnmapBuffer"); assert(glUnmapBuffer);
        glGetBufferParameteriv  = (PFNGLGETBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetBufferParameteriv"); assert(glGetBufferParameteriv);
        glGetBufferPointerv  = (PFNGLGETBUFFERPOINTERVPROC)wglGetProcAddress("glGetBufferPointerv"); assert(glGetBufferPointerv);
    }

    // OpenGL 2.0 and above
    if( checkGLVersion( 2,0 ) )
    {
          glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)wglGetProcAddress("glBlendEquationSeparate"); assert(glBlendEquationSeparate);
                    glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers"); assert(glDrawBuffers);
              glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)wglGetProcAddress("glStencilOpSeparate"); assert(glStencilOpSeparate);
            glStencilFuncSeparate  = (PFNGLSTENCILFUNCSEPARATEPROC)wglGetProcAddress("glStencilFuncSeparate"); assert(glStencilFuncSeparate);
            glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)wglGetProcAddress("glStencilMaskSeparate"); assert(glStencilMaskSeparate);
                   glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader"); assert(glAttachShader);
             glBindAttribLocation  = (PFNGLBINDATTRIBLOCATIONPROC)wglGetProcAddress("glBindAttribLocation"); assert(glBindAttribLocation);
                  glCompileShader  = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"); assert(glCompileShader);
                  glCreateProgram  = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram"); assert(glCreateProgram);
                   glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"); assert(glCreateShader);
                  glDeleteProgram = (PFNGLDELETEPROGRAMPROC)wglGetProcAddress("glDeleteProgram"); assert(glDeleteProgram);
                   glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader"); assert(glDeleteShader);
                   glDetachShader = (PFNGLDETACHSHADERPROC)wglGetProcAddress("glDetachShader"); assert(glDetachShader);
           glDisableVertexAttribArray  = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glDisableVertexAttribArray"); assert(glDisableVertexAttribArray);
            /*glEnableVertexAttribArray  = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress(""); assert();
                glGetActiveAttrib  = (PFNGLGETACTIVEATTRIBPROC)wglGetProcAddress(""); assert();
               glGetActiveUniform  = (PFNGLGETACTIVEUNIFORMPROC)wglGetProcAddress(""); assert();
             glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)wglGetProcAddress(""); assert();
              glGetAttribLocation  = (PFNGLGETATTRIBLOCATIONPROC)wglGetProcAddress(""); assert();
                   glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress(""); assert();
              glGetProgramInfoLog  = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress(""); assert();
                    glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress(""); assert();
               glGetShaderInfoLog  = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress(""); assert();
                glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)wglGetProcAddress(""); assert();
             glGetUniformLocation  = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress(""); assert();
                   glGetUniformfv  = (PFNGLGETUNIFORMFVPROC)wglGetProcAddress(""); assert();
                   glGetUniformiv  = (PFNGLGETUNIFORMIVPROC)wglGetProcAddress(""); assert();
              glGetVertexAttribdv  = (PFNGLGETVERTEXATTRIBDVPROC)wglGetProcAddress(""); assert();
              glGetVertexAttribfv  = (PFNGLGETVERTEXATTRIBFVPROC)wglGetProcAddress(""); assert();
              glGetVertexAttribiv  = (PFNGLGETVERTEXATTRIBIVPROC)wglGetProcAddress(""); assert();
         glGetVertexAttribPointerv  = (PFNGLGETVERTEXATTRIBPOINTERVPROC)wglGetProcAddress(""); assert();
                      glIsProgram  = (PFNGLISPROGRAMPROC)wglGetProcAddress(""); assert();
                       glIsShader  = (PFNGLISSHADERPROC)wglGetProcAddress(""); assert();
                    glLinkProgram  = (PFNGLLINKPROGRAMPROC)wglGetProcAddress(""); assert();
                   glShaderSource  = (PFNGLSHADERSOURCEPROC)wglGetProcAddress(""); assert();
                     glUseProgram  = (PFNGLUSEPROGRAMPROC)wglGetProcAddress(""); assert();
                      glUniform1f  = (PFNGLUNIFORM1FPROC)wglGetProcAddress(""); assert();
                      glUniform2f  = (PFNGLUNIFORM2FPROC)wglGetProcAddress(""); assert();
                      glUniform3f  = (PFNGLUNIFORM3FPROC)wglGetProcAddress(""); assert();
                      glUniform4f  = (PFNGLUNIFORM4FPROC)wglGetProcAddress(""); assert();
                      glUniform1i  = (PFNGLUNIFORM1IPROC)wglGetProcAddress(""); assert();
                      glUniform2i  = (PFNGLUNIFORM2IPROC)wglGetProcAddress(""); assert();
                      glUniform3i  = (PFNGLUNIFORM3IPROC)wglGetProcAddress(""); assert();
                      glUniform4i  = (PFNGLUNIFORM4IPROC)wglGetProcAddress(""); assert();
                     glUniform1fv  = (PFNGLUNIFORM1FVPROC)wglGetProcAddress(""); assert();
                     glUniform2fv  = (PFNGLUNIFORM2FVPROC)wglGetProcAddress(""); assert();
                     glUniform3fv  = (PFNGLUNIFORM3FVPROC)wglGetProcAddress(""); assert();
                     glUniform4fv  = (PFNGLUNIFORM4FVPROC)wglGetProcAddress(""); assert();
                     glUniform1iv  = (PFNGLUNIFORM1IVPROC)wglGetProcAddress(""); assert();
                     glUniform2iv  = (PFNGLUNIFORM2IVPROC)wglGetProcAddress(""); assert();
                     glUniform3iv  = (PFNGLUNIFORM3IVPROC)wglGetProcAddress(""); assert();
                     glUniform4iv  = (PFNGLUNIFORM4IVPROC)wglGetProcAddress(""); assert();
               glUniformMatrix2fv  = (PFNGLUNIFORMMATRIX2FVPROC)wglGetProcAddress(""); assert();
               glUniformMatrix3fv  = (PFNGLUNIFORMMATRIX3FVPROC)wglGetProcAddress(""); assert();
               glUniformMatrix4fv  = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress(""); assert();
                glValidateProgram  = (PFNGLVALIDATEPROGRAMPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib1d  = (PFNGLVERTEXATTRIB1DPROC)wglGetProcAddress(""); assert();
                glVertexAttrib1dv  = (PFNGLVERTEXATTRIB1DVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib1f  = (PFNGLVERTEXATTRIB1FPROC)wglGetProcAddress(""); assert();
                glVertexAttrib1fv  = (PFNGLVERTEXATTRIB1FVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib1s  = (PFNGLVERTEXATTRIB1SPROC)wglGetProcAddress(""); assert();
                glVertexAttrib1sv  = (PFNGLVERTEXATTRIB1SVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib2d  = (PFNGLVERTEXATTRIB2DPROC)wglGetProcAddress(""); assert();
                glVertexAttrib2dv  = (PFNGLVERTEXATTRIB2DVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib2f  = (PFNGLVERTEXATTRIB2FPROC)wglGetProcAddress(""); assert();
                glVertexAttrib2fv  = (PFNGLVERTEXATTRIB2FVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib2s  = (PFNGLVERTEXATTRIB2SPROC)wglGetProcAddress(""); assert();
                glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib3d  = (PFNGLVERTEXATTRIB3DPROC)wglGetProcAddress(""); assert();
                glVertexAttrib3dv  = (PFNGLVERTEXATTRIB3DVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib3f  = (PFNGLVERTEXATTRIB3FPROC)wglGetProcAddress(""); assert();
                glVertexAttrib3fv  = (PFNGLVERTEXATTRIB3FVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib3s  = (PFNGLVERTEXATTRIB3SPROC)wglGetProcAddress(""); assert();
                glVertexAttrib3sv  = (PFNGLVERTEXATTRIB3SVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4Nbv  = (PFNGLVERTEXATTRIB4NBVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4Niv  = (PFNGLVERTEXATTRIB4NIVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4Nsv  = (PFNGLVERTEXATTRIB4NSVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4Nub  = (PFNGLVERTEXATTRIB4NUBPROC)wglGetProcAddress(""); assert();
              glVertexAttrib4Nubv  = (PFNGLVERTEXATTRIB4NUBVPROC)wglGetProcAddress(""); assert();
              glVertexAttrib4Nuiv  = (PFNGLVERTEXATTRIB4NUIVPROC)wglGetProcAddress(""); assert();
              glVertexAttrib4Nusv  = (PFNGLVERTEXATTRIB4NUSVPROC)wglGetProcAddress(""); assert();
                glVertexAttrib4bv  = (PFNGLVERTEXATTRIB4BVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib4d  = (PFNGLVERTEXATTRIB4DPROC)wglGetProcAddress(""); assert();
                glVertexAttrib4dv  = (PFNGLVERTEXATTRIB4DVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib4f  = (PFNGLVERTEXATTRIB4FPROC)wglGetProcAddress(""); assert();
                glVertexAttrib4fv  = (PFNGLVERTEXATTRIB4FVPROC)wglGetProcAddress(""); assert();
                glVertexAttrib4iv  = (PFNGLVERTEXATTRIB4IVPROC)wglGetProcAddress(""); assert();
                 glVertexAttrib4s  = (PFNGLVERTEXATTRIB4SPROC)wglGetProcAddress(""); assert();
                glVertexAttrib4sv  = (PFNGLVERTEXATTRIB4SVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4ubv  = (PFNGLVERTEXATTRIB4UBVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4uiv  = (PFNGLVERTEXATTRIB4UIVPROC)wglGetProcAddress(""); assert();
               glVertexAttrib4usv  = (PFNGLVERTEXATTRIB4USVPROC)wglGetProcAddress(""); assert();
            glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress(""); assert();*/
    }
    
}

//=============================================================================
/**
** <summary>Destroys an OpenGL graphics driver</summary>
**
*/
int InitGL(GLvoid)                                        // All Setup For OpenGL Goes Here
{
    // Init the api functions
    InitOpenGLAPI();

    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                // Black Background
    glClearDepth(1.0f);                                    // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                                // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // Really Nice Perspective Calculations
    return TRUE;                                        // Initialization Went OK
}

//=============================================================================
/**
** <summary>Gets the name of the graphics driver</summary>
**
*/
const std::wstring & OpenGLGraphicsDriver::getName() const 
{
    static wstring sName(L"OpenGL graphics driver");
    return sName;
}

//=============================================================================
/**
** <summary>Creates a renderer</summary>
**
*/
Omen::IRenderer* OpenGLGraphicsDriver::createRenderer() 
{
    m_renderer = new OpenGLRenderer();
    m_renderer->m_window.createWindow(1024,1024,false);
    return m_renderer;
}

void OpenGLRenderer::beginRendering() const 
{
}

void OpenGLRenderer::endRendering() const 
{
}

void OpenGLRenderer::render(Omen::ICamera* pCamera) const
{
}

void OpenGLRenderer::render(Omen::ILight** pLights, unsigned int numLights) const
{
}

void OpenGLRenderer::render(Omen::IModel** pCameras, unsigned int numModels) const
{
}

static void CreateVertexBufferObject()
{
    GLuint vbo;
    
    glGenBuffers(1, &vbo); 
    assert( glIsBuffer(vbo) );

    GLuint pbo;
    glGenBuffers(1, &pbo);
    assert( glIsBuffer(pbo) );
}


//=============================================================================
/**
**  <summary> This will initialize the OpenGL Graphics driver class</summary>
**
*/
void OpenGLGraphicsDriver::initialize()
{
    m_renderer->m_window.createWindow(1024, 1024, false );
    InitGL();
    CreateVertexBufferObject();
}



OpenGLRenderer::OpenGLRenderer()
{
}

unsigned long OpenGLRenderer::windowHandle() const 
{
    return m_window.windowHandle();
}

/// <summary>Renderer creates a vertex buffer for this mesh</summary>
void OpenGLRenderer::createVertexBuffer( IMesh* pMesh ) const
{
}

/// <summary>Renderer creates an index buffer for this mesh</summary>
void OpenGLRenderer::createIndexBuffer( IMesh* pMesh ) const
{
}

/// <summary>Create a shader with given name</summary>
bool OpenGLRenderer::createShader( const std::wstring& shaderName, Omen::IShader*& pShader ) const 
{
    return false;
}

